
實作一個 Webcam ,有拍照、下載、濾鏡的效果
在驅動 webcam 前需要有一個 localhost 服務器,檔案裡有 package.json 先跑安裝檔
npm來安裝browser-sync:npm i啟動視訊
建立 func: getVideo
function getVideo() {}
利用 navigator.mediaDevices.getUserMedia 取得 User 的視訊裝置
 navigator.mediaDevices.getUserMedia({ video: true, audio: false })
    .then(localMediaStream => {
	    // 有取得要做的事
    })
    .catch(err => {
      console.error(`oh no`, err);
    });
console MediaStream 看一下,再把回傳的 MediaStream 寫到 HTML 中的 video tag ,然後播放出來。
video.srcObject = localMediaStream;
video.play();
打開鏡頭就可以看到自己了0.0
把畫面繪製到 canvas 上面
建立 func: paintToCanvas
function paintToCanvas() {}
canvas 寬高:取得 video 的寬高再賦值給 canvas
const width = video.videoWidth;
const height = video.videoHeight;
canvas.width = width;
canvas.height = height;
使用 setInterval drawImage 繪製上去
return setInterval(() => {
	//            畫哪裡,從哪畫, 畫到哪
  ctx.drawImage(video, 0, 0, width, height);
}, 16);
拍照功能
建立 func: takePhoto
function takePhoto() {}
先製作拍照的聲音
snap.currentTime = 0;
snap.play();
新增點擊觸發事件
video.addEventListener('canplay', paintToCanvas);
把照片取出 base64 的字串
const data = canvas.toDataURL('image/jpeg');
呈現在畫面上
先製作一個 a 連結並儲存
const link = document.createElement('a')
link.href = data;
畫面呈現
link.innerHTML = `<img src="${data}" alt="By takePhoto"/>`
點擊 a 圖片下載
//                  屬性
link.setAttribute('download', 'takePhoto')
把照片插在節點前面 MDN
strip.insertBefore(link, strip.firstChild)
加上紅色濾鏡
使用 getImageData 取出 canvas 像素 func: paintToCanvas→ setInterval
let pixels = ctx.getImageData(0, 0, width, height);
		pixels = redEffect(pixels);
建立 func: redEffect 帶入 pixels 的參數
function redEffect(pixels) {
//                                       一組 rgba 的顏色
  for (let i = 0; i < pixels.data.length; i += 4) {
    pixels.data[i + 0] = pixels.data[i + 0] + 100; // RED
    pixels.data[i + 1] = pixels.data[i + 1] - 50; // GREEN
    pixels.data[i + 2] = pixels.data[i + 2] * 0.5; // BLUE
  }
  return pixels
}
使用 putImageData 改變 canvas func: paintToCanvas→ setInterval
pixels = redEffect(pixels);
ctx.putImageData(pixels, 0, 0);
畫面分割 : 把顏色位移
建立 func: rgbSplit 帶入 pixels 的參數
function rgbSplit(pixels) {
  for (let i = 0; i < pixels.data.length; i += 4) {
    pixels.data[i - 150] = pixels.data[i + 0]; // RED
    pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
    pixels.data[i - 500] = pixels.data[i + 2]; // BLUE
  }
  return pixels
}
修改上方 pixels 值,加上效果
// pixels = redEffect(pixels);
   pixels = rgbSplit(pixels)
	 ctx.globalAlpha = 0.1
加上綠色濾鏡
修改上方 pixels 值,加上效果 func: paintToCanvas→ setInterval
pixels = greenScreen(pixels);
建立 func: greenScreen 帶入 pixels 的參數
function greenScreen(pixels) {
  const levels = {};
  // 設定範圍
  document.querySelectorAll('.rgb input').forEach((input) => {
    levels[input.name] = input.value;
  });
  for (i = 0; i < pixels.data.length; i = i + 4) {
    red = pixels.data[i + 0];
    green = pixels.data[i + 1];
    blue = pixels.data[i + 2];
    alpha = pixels.data[i + 3];
    if (red >= levels.rmin
      && green >= levels.gmin
      && blue >= levels.bmin
      && red <= levels.rmax
      && green <= levels.gmax
      && blue <= levels.bmax) {
      // rgb 的顏色在相對中間就把 alpha 調成 0,那點就不見
      pixels.data[i + 3] = 0;
    }
  }
  return pixels;
}
修改上方 pixels 值,加上效果
// pixels = redEffect(pixels);
   pixels = greenScreen(pixels);